package ru.pb.auth.network.threading;

import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import ru.pb.global.configs.DevelopConfig;
import ru.pb.global.threading.IThreadExecute;
import ru.pb.global.threading.PriorityThreadFactory;

public class ThreadPoolManager implements IThreadExecute
{
	private ScheduledThreadPoolExecutor _poolExecute;

	private static ThreadPoolManager _instance;

	public static ThreadPoolManager getInstance()
	{
		if(_instance == null)
			_instance = new ThreadPoolManager();
		return _instance;
	}

	ThreadPoolManager()
	{
		_poolExecute = new ScheduledThreadPoolExecutor(DevelopConfig.POOL_SIZE, new PriorityThreadFactory("General Packet Pool", Thread.NORM_PRIORITY + 2));
	}

	private boolean _shutdown;

	public boolean isShutdown()
	{
		return _shutdown;
	}

	public void shutdown()
	{
		_shutdown = true;
		try
		{
			_poolExecute.awaitTermination(1, TimeUnit.SECONDS);
			_poolExecute.shutdown();

			Logger.getLogger(ThreadPoolManager.class).info("All ThreadPools are now stoped.");
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	public <T extends Runnable>ScheduledFuture<T> scheduleAtFixedRate(T r, long initial, long delay)
	{
		try
		{
			// log(r.getClass(), "schedule");
			return (ScheduledFuture<T>) _poolExecute.scheduleAtFixedRate(r, correctTime(initial), correctTime(delay), TimeUnit.MILLISECONDS);
		}
		catch(RejectedExecutionException e)
		{
			if( !isShutdown())
			{
				Logger.getLogger(ThreadPoolManager.class).info("Exception: " + e, e);
			}
			return null;
		}
	}

	private long correctTime(long g)
	{
		if(g <= 0)
			g = 1;

		return g;
	}

	@Override
	public void execute(Runnable r)
	{
		_poolExecute.execute(r);
	}

	@Override
	public ScheduledFuture schedule(Runnable rub, long t1)
	{
		return _poolExecute.schedule(rub, t1, TimeUnit.MILLISECONDS);
	}
}